/**
 * 
 */
package fr.sinno.wms.batch.utils;

import java.io.BufferedReader;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;

import fr.sinno.wms.batch.model.DetailBonLivraison;
import fr.sinno.wms.batch.model.HeaderBonlivraison;
import fr.sinno.wms.batch.model.HeaderCommand;
import fr.sinno.wms.batch.model.LineBonLivraison;
import fr.sinno.wms.batch.model.LineCommand;
import fr.sinno.wms.batch.model.LotBonLivraison;

/**
 * @author HP
 *
 */
@Service
public class ConvertManager {

	private static final Logger LOG = Logger.getLogger(ConvertManager.class);

	private static SimpleDateFormat dateFormat = new SimpleDateFormat(
	"yyyyMMddHHmmss");

	private static DecimalFormat decimalFormat = new DecimalFormat("0000000.00000");

	/**
	 * Convert String to {@link HeaderBonlivraison}
	 * 
	 * @param header
	 *            input Header
	 * @return {@link HeaderBonlivraison} object
	 */
	public HeaderBonlivraison transformeHeader(String header) {

		HeaderBonlivraison headerBL = new HeaderBonlivraison();

		headerBL.setWarehouseCode(header.substring(0, 10).trim());
		String sorterCode = header.substring(10, 60).trim();
		if (!"".equals(sorterCode)) {
			if (sorterCode.contains("/")) {
				sorterCode = sorterCode.substring(0, sorterCode.indexOf("/"));
			}
		}
		headerBL.setSorterCode(sorterCode);
		headerBL.setStatus(header.substring(60, 90).trim());
		Date date = null;
		try {
			date = dateFormat.parse(header.substring(90, 104).trim());
		} catch (ParseException e) {
			LOG.info("CHAMPS Date(90,104) INCORRECTE : " + e.getMessage());
		}
		headerBL.setDate(date);
		headerBL.setDoorCode(header.substring(104, 116).trim());
		headerBL.setDriverName(header.substring(116, 156).trim());
		headerBL.setDriverName2(header.substring(156, 196).trim());
		headerBL.setTruck(header.substring(196, 216).trim());
		headerBL.setTruck2(header.substring(216, 236).trim());
		headerBL.setDocument(header.substring(236, 286).trim());
		headerBL.setCarrierCode(header.substring(286, 306).trim());
		headerBL.setSupplierCode(header.substring(306, 326).trim());
		headerBL.setAccountCode(header.substring(326, 338).trim());
		headerBL.setWarehouseCodeTo(header.substring(338, 348).trim());
		try {
			headerBL.setTotalNumberContains(Integer.parseInt(header.substring(
					348, 358).trim()));
			headerBL.setNumberOfLigne(Integer.parseInt(header.substring(358,
					368).trim()));
		} catch (NumberFormatException numberException) {
			LOG.error("ERREUR FORMAT INTEGER HEADER : "
					+ numberException.getMessage());
		}

		return headerBL;
	}

	/**
	 * Convert String to {@link LineBonLivraison}
	 * 
	 * @param line
	 *            String to convert
	 * @param br
	 * @return {@link LineBonLivraison} object
	 */
	public LineBonLivraison transformeLineBonLivraison(String line,
			BufferedReader br) {

		LineBonLivraison lineBL = new LineBonLivraison();

		int lineNum = 0;
		try {
			lineNum = Integer.parseInt(line.substring(0, 10).trim());
		} catch (NumberFormatException numberException) {
			LOG.info("CHAMPS LineNumber(0,10) INCORRECTE : "
					+ numberException.getMessage());
		}
		lineBL.setLineNumber(lineNum);

		lineBL.setCustLineNumber(line.substring(10, 60).trim());
		lineBL.setProductCode(line.substring(60, 110).trim());
		lineBL.setLotCode(line.substring(110, 160).trim());

		String tmp = line.substring(160, 172).trim();
		Double quantity = 0.0;
		try {
			quantity = parseDouble(tmp);
		} catch (NumberFormatException numberException) {
			LOG.info("CHAMPS Quantity(160,172) INCORRECTE : "
					+ numberException.getMessage());
		}
		lineBL.setQuantity(quantity);

		lineBL.setSerialNO(line.substring(172, 222).trim());

		tmp = line.substring(222, 236).trim();
		Date expiryDate = null;
		try {
			if (null != tmp && !"".equals(tmp)) {
				expiryDate = dateFormat.parse(tmp);
			}
		} catch (ParseException e) {
			LOG.info("CHAMPS ExpiryDate(222,236) INCORRECTE : "
					+ e.getMessage());
		}
		lineBL.setExpiryDate(expiryDate);

		lineBL.setUomCode(line.substring(236, 246).trim());

		tmp = line.substring(246, 258).trim();
		Double salePrice = 0.0;
		try {
			if (null != tmp && !"".equals(tmp)) {
				salePrice = parseDouble(tmp);
			}
		} catch (NumberFormatException numberException) {
			LOG.info("CHAMPS SalePrice(246,258) INCORRECTE : "
					+ numberException.getMessage());
		}
		lineBL.setSalePrice(salePrice);

		lineBL.setQuality(line.substring(258, 308).trim());

		tmp = line.substring(308, 322).trim();
		Date bestBeforeDate = null;
		try {
			if (null != tmp && !"".equals(tmp)) {
				bestBeforeDate = dateFormat.parse(tmp);
			}
		} catch (ParseException e) {
			LOG.info("CHAMPS BestBeforeDate(308,322) INCORRECTE : "
					+ e.getMessage());
		}
		lineBL.setBestBeforeDate(bestBeforeDate);

		tmp = line.substring(322, 334).trim();
		Double minShelfLife = 0.0;
		try {
			if (null != tmp && !"".equals(tmp)) {
				minShelfLife = parseDouble(tmp);
			}
		} catch (NumberFormatException numberException) {
			LOG.info("CHAMPS MinShelfLife(322,334) INCORRECTE : "
					+ numberException.getMessage());
		}
		lineBL.setMinShelfLife(minShelfLife);

		tmp = line.substring(334, 346).trim();
		Double servedQuantity = 0.0;
		try {
			servedQuantity = parseDouble(tmp);
		} catch (NumberFormatException numberException) {
			LOG.info("CHAMPS ServedQuantity(334,346) INCORRECTE : "
					+ numberException.getMessage());
		}
		lineBL.setServedQuantity(servedQuantity);

		tmp = line.substring(346, 358).trim();
		Double weight = 0.0;
		try {
			weight = parseDouble(tmp);
		} catch (NumberFormatException numberException) {
			LOG.info("CHAMPS Weight(346,358) INCORRECTE : "
					+ numberException.getMessage());
		}
		lineBL.setWeight(weight);

		Date date = null;
		try {
			date = dateFormat.parse(line.substring(358, 372));
		} catch (ParseException parseException) {
			LOG.info("CHAMPS Date(358,372) INCORRECTE : "
					+ parseException.getMessage());
		}
		lineBL.setDate(date);

		tmp = line.substring(372, 384).trim();
		Double qttyOrdered = 0.0;
		try {
			qttyOrdered = parseDouble(tmp);
		} catch (NumberFormatException numberException) {
			LOG.info("CHAMPS QttyOrdered(372,284) INCORRECTE : "
					+ numberException.getMessage());
		}
		lineBL.setQttyOrdered(qttyOrdered);

		tmp = line.substring(384, 396).trim();
		Double qttyShipped = 0.0;
		try {
			qttyShipped = parseDouble(tmp);
		} catch (NumberFormatException numberException) {
			LOG.info("CHAMPS QttyShipped(384,396) INCORRECTE : "
					+ numberException.getMessage());
		}
		lineBL.setQttyShipped(qttyShipped);

		tmp = line.substring(396, 408).trim();
		Double qttySubstituted = 0.0;
		try {
			qttySubstituted = parseDouble(tmp);
		} catch (NumberFormatException numberException) {
			LOG.info("CHAMPS QttySubstituted(396,408) INCORRECTE : "
					+ numberException.getMessage());
		}
		lineBL.setQttySubstituted(qttySubstituted);

		tmp = line.substring(408, 420).trim();
		Double qttyDamaged = 0.0;
		try {
			qttyDamaged = parseDouble(tmp);
		} catch (NumberFormatException numberException) {
			LOG.info("CHAMPS QttyDamaged(408,420) INCORRECTE : "
					+ numberException.getMessage());
		}
		lineBL.setQttyDamaged(qttyDamaged);

		tmp = line.substring(420, 432).trim();
		Double qttyRefused = 0.0;
		try {
			qttyRefused = parseDouble(tmp);
		} catch (NumberFormatException numberException) {
			LOG.info("CHAMPS QttyRefused(420,432) INCORRECTE : "
					+ numberException.getMessage());
		}
		lineBL.setQttyRefused(qttyRefused);

		tmp = line.substring(432, 444).trim();
		Double QttyAllocByHost = 0.0;
		try {
			QttyAllocByHost = parseDouble(tmp);
		} catch (NumberFormatException numberException) {
			LOG.info("CHAMPS QttyAllocByHost(432,444) INCORRECTE : "
					+ numberException.getMessage());
		}
		lineBL.setQttyAllocByHost(QttyAllocByHost);

		int numDetails = 0;
		try {
			numDetails = Integer.parseInt(line.substring(444, 454).trim());
		} catch (NumberFormatException numberException) {
			LOG.info("CHAMPS NumDetails(444,454) INCORRECTE : "
					+ numberException.getMessage());
		}
		lineBL.setNumDetails(numDetails);

		int numLots = 0;
		try {
			numLots = Integer.parseInt(line.substring(454, 464).trim());
		} catch (NumberFormatException numberException) {
			LOG.info("CHAMPS NumLot(454,464) INCORRECTE : "
					+ numberException.getMessage());
		}
		lineBL.setNumLot(numLots);

		try {

			DetailBonLivraison bonLivraisonDetail;
			String ligneDetail;
			for (int i = 0; i < numDetails; i++) {
				ligneDetail = br.readLine();
				bonLivraisonDetail = transformeBonLivraisonDetail(ligneDetail);

				lineBL.addBonLivraisonDetail(bonLivraisonDetail);
			}

			LotBonLivraison bonLivraisonLot;
			String ligneLot;
			for (int i = 0; i < numLots; i++) {
				ligneLot = br.readLine();
				bonLivraisonLot = transformeBonLivraisonLot(ligneLot);

				lineBL.addBonLivraisonLot(bonLivraisonLot);
			}

		} catch (Exception e) {
			e.printStackTrace();
		}

		return lineBL;
	}

	/**
	 * 
	 * @param lineLot
	 * @return
	 */
	private LotBonLivraison transformeBonLivraisonLot(String lineLot) {
		LotBonLivraison retour = new LotBonLivraison();

		return retour;
	}

	/**
	 * Convert String to {@link DetailBonLivraison}
	 * 
	 * @param line
	 * @return {@link DetailBonLivraison} object
	 */
	private DetailBonLivraison transformeBonLivraisonDetail(String line) {
		DetailBonLivraison detail = new DetailBonLivraison();

		detail.setClientContainerNo(line.substring(0, 50).trim());
		detail.setSourceContainerNo(line.substring(50, 100).trim());
		detail.setProductCode(line.substring(100, 150).trim());
		detail.setUomCode(line.substring(150, 160).trim());

		String tmp = line.substring(160, 172).trim();
		Double shippedQtty = 0.0;
		try {
			shippedQtty = parseDouble(tmp);
		} catch (NumberFormatException numberException) {
			LOG.info("CHAMPS ShippedQuantity(160,172) INCORRECTE : "
					+ numberException.getMessage());
		}
		detail.setQttyShipped(shippedQtty);

		tmp = line.substring(172, 184).trim();
		Double shippedWeight = 0.0;
		try {
			shippedWeight = parseDouble(tmp);
		} catch (NumberFormatException numberException) {
			LOG.info("CHAMPS ShippedWeight(172,184) INCORRECTE : "
					+ numberException.getMessage());
		}
		detail.setWeightShipped(shippedWeight);

		tmp = line.substring(184, 198).trim();
		Date shipDate = null;
		try {
			if (null != tmp && !"".equals(tmp)) {
				shipDate = dateFormat.parse(tmp);
			}
		} catch (ParseException e) {
			LOG.info("CHAMPS ShipDate(184, 198) INCORRECTE : "
					+ e.getMessage());
		}
		detail.setShippDate(shipDate);
		
		detail.setLotCode(line.substring(198, 248).trim());
		detail.setSupplierCode(line.substring(248, 268).trim());
		detail.setSerialNO(line.substring(268, 318).trim());
		
		tmp = line.substring(318, 332).trim();
		Date expiryDate = null;
		try {
			if (null != tmp && !"".equals(tmp)) {
				expiryDate = dateFormat.parse(tmp);
			}
		} catch (ParseException e) {
			LOG.info("CHAMPS ExpiryDate(318, 332) INCORRECTE : "
					+ e.getMessage());
		}
		detail.setExpiryDate(expiryDate);
		
		detail.setQuality(line.substring(332, 382).trim());

		tmp = line.substring(382, 396).trim();
		Date bestBeforDate = null;
		try {
			if (null != tmp && !"".equals(tmp)) {
				bestBeforDate = dateFormat.parse(tmp);
			}
		} catch (ParseException e) {
			LOG.info("CHAMPS BestBeforDate(382, 396) INCORRECTE : "
					+ e.getMessage());
		}
		detail.setBestBeforeDate(bestBeforDate);
		
		tmp = line.substring(396, 410).trim();
		Date productionDate = null;
		try {
			if (null != tmp && !"".equals(tmp)) {
				productionDate = dateFormat.parse(tmp);
			}
		} catch (ParseException e) {
			LOG.info("CHAMPS ProductionDate(396, 410) INCORRECTE : "
					+ e.getMessage());
		}
		detail.setProductionDate(productionDate);
	
		tmp = line.substring(410, 422).trim();
		Double shelfLife = 0.0;
		try {
			shelfLife = parseDouble(tmp);
		} catch (NumberFormatException numberException) {
			LOG.info("CHAMPS ShelfLife(410, 422) INCORRECTE : "
					+ numberException.getMessage());
		}
		detail.setShelfLife(shelfLife);

		detail.setOwnerCode(line.substring(422, 434).trim());
		detail.setPack(line.substring(434, 484).trim());
	
		tmp = line.substring(484, 498).trim();
		Date dateDaysOfLife = null;
		try {
			if (null != tmp && !"".equals(tmp)) {
				dateDaysOfLife = dateFormat.parse(tmp);
			}
		} catch (ParseException e) {
			LOG.info("CHAMPS DateDaysOfLife(484, 498) INCORRECTE : "
					+ e.getMessage());
		}
		detail.setDateDaysOfLife(dateDaysOfLife);

		detail.setSizeCode(line.substring(498, 548).trim());
		detail.setColorCode(line.substring(548, 598).trim());
		detail.setSource(line.substring(598, 648).trim());
		detail.setVersionCode(line.substring(648, 698).trim());
		detail.setProductionMethod(line.substring(698, 748).trim());
		detail.setPostProductionTreatment(line.substring(748, 798).trim());
		
		return detail;
	}

	/**
	 * Convert String to Double
	 * @param text String
	 * @return Double
	 */
	private Double parseDouble(String text) {
		if (null != text && !"".equals(text) && text.length() == 12) {
			return new Double(text.substring(0, 7) + "." + text.substring(7, 12));
		} else {
			return 0.0;
		}
	}

	public String convertHeaderCommandToString(HeaderCommand header, int nbLigne, String type) {
		
		//32
		StringBuffer resultat = new StringBuffer();

		// NOUVELLE COMMANDE : A
		//  COMMANDE AVEC RETOUR ET RELIQUAT : B = SUPPRESSION 
		String operation = type;
		resultat.append(operation);
		
		String sorderCode = formatString(header.getCode(), 50);
		resultat.append(sorderCode);
	
		String warehouseCode = formatString("DANI", 10);
		resultat.append(warehouseCode);
		
		String description = formatString("", 100);
		resultat.append(description);
		
		String comment = formatString("", 255);
		resultat.append(comment);
		
		String typeCode = formatString("CORDER", 30);
		resultat.append(typeCode);
		
		String typeDescription = formatString("", 100);
		resultat.append(typeDescription);
		
		String priority = formatNumber(new Double(0), 10);
		resultat.append(priority);
		
		String accountCode = formatString(header.getCodeTiers(), 12);
		resultat.append(accountCode);
		
		String stagingLocCode = formatString("", 12);
		resultat.append(stagingLocCode);
		
		String doorCode = formatString("", 12);
		resultat.append(doorCode);
	
		String routeCode = formatString("", 50);
		resultat.append(routeCode);
		
		
		String stopNumber = formatString("", 10);
		resultat.append(stopNumber);
		
		String carrierCode = formatString("", 20);
		resultat.append(carrierCode);
		
		String containerTypeCode = formatString("", 10);
		resultat.append(containerTypeCode);
		
		String document = formatString("", 50);
		resultat.append(document);
		
		String transportType = formatString("", 50);
		resultat.append(transportType);
		
		String source = formatString("", 50);
		resultat.append(source);
		
		String deliveryInst = formatString("", 255);
		resultat.append(deliveryInst);
		
		String allocateDate = formatDate(null);
		resultat.append(allocateDate);
		
		String processDate = formatDate(null);
		resultat.append(processDate);
		
		String shippingDate = formatDate(null);
		resultat.append(shippingDate);
		
		String planedLoadDate = formatDate(null);
		resultat.append(planedLoadDate);
		
		String containers = formatString("", 12);
		resultat.append(containers);
		
		String verifyStock = "0";
		resultat.append(verifyStock);
		
		String followSequence = " ";
		resultat.append(followSequence);
		
		String releaseDate = formatDate(null);
		resultat.append(releaseDate);
		
		String supplierCode = formatString("", 20);
		resultat.append(supplierCode);

		String autoReserveDate = formatDate(null);
		resultat.append(autoReserveDate);
		
		String validDate = formatDate(null);
		resultat.append(validDate);

		String warehouseCodeDest = formatString("", 10);
		resultat.append(warehouseCodeDest);

		String attribute = "[][][][][][][][][][][][][][][][][][][][]";
		resultat.append(attribute);
		
		String lineCount = formatInt(nbLigne, 10);
		resultat.append(lineCount);

		resultat.append("\n");

		return resultat.toString();
	}

	public String convertLineCommandToString(LineCommand line) {

		//45
		StringBuffer resultat = new StringBuffer("/");

		resultat.append(formatNumber(line.getNumeroLigne(), 10));

		String codeArticle = formatString(line.getCodeArticle(), 50);
		resultat.append(codeArticle);

		String codeLot = formatString(line.getCodeLot(), 50);
		resultat.append(codeLot);

		if (null != line.getQuantite() && null != line.getQteLivree()) {
			String quantite = formatDouble(line.getQuantite() - line.getQteLivree());
			resultat.append(quantite);
		} else {
			String quantite = formatDouble(0.0);
			resultat.append(quantite);
		}

		String codeEAN = formatString("", 50);
		resultat.append(codeEAN);

		String serialNo = formatString("", 50);
		resultat.append(serialNo);

		String dateExpiration = formatDate(null);
		resultat.append(dateExpiration);

		String shelfDays = formatNumber(null, 10);
		resultat.append(shelfDays);

		String uomCode = formatString("UN", 10);
		resultat.append(uomCode);

		String requiredToShip = "0";
		resultat.append(requiredToShip);

		String comment = formatString("", 255);
		resultat.append(comment);
		
		String isCristal = " ";
		resultat.append(isCristal);

		String custLineNo = formatString("", 50);
		resultat.append(custLineNo);
		
		String dateExpedition = formatDate(null);
		resultat.append(dateExpedition);
		
		String customerCode = formatString(line.getCodeTiers(), 50);
		resultat.append(customerCode);
		
		String requireStatusCode = formatString("", 3);
		resultat.append(requireStatusCode);
		
		String rejectStatusCode = formatString("", 3);
		resultat.append(rejectStatusCode);
		
		String ownerCode = formatString("", 12);
		resultat.append(ownerCode);
		
		String prefRequestStatusCode = formatString("", 3);
		resultat.append(prefRequestStatusCode);

		String containeNo = formatString("", 50);
		resultat.append(containeNo);

		// DES ESPACES
		String quatityToReserve = formatDouble(null);
		resultat.append(quatityToReserve);
		
		String serieControl = " ";
		resultat.append(serieControl);
		
	// DES  ESPACES
		String salePrice = formatDouble(null);
		resultat.append(salePrice);
		
		String labelNo = formatNumber(null, 3);
		resultat.append(labelNo);
		
		String containerTypeCode = formatString("", 10);
		resultat.append(containerTypeCode);
		
		String substitudProdCode = formatString("", 50);
		resultat.append(substitudProdCode);
		
		String preferableUomCode = formatString("", 10);
		resultat.append(preferableUomCode);
		
		// DES ESPACES
		String minSheftLife = formatDouble(null);
		resultat.append(minSheftLife);
		
		String roudControl = " ";
		resultat.append(roudControl);
		
		String mixedLogisctic = " ";
		resultat.append(mixedLogisctic);
		
		String quality = formatString("", 50);
		resultat.append(quality);

		String bestBeforeDate = formatDate(null);
		resultat.append(bestBeforeDate);

		String locationLabel = formatString("", 20);
		resultat.append(locationLabel);
		
		String catchWeight = "0";
		resultat.append(catchWeight);

		String substituteQtty = formatDouble(new Double(0));
		resultat.append(substituteQtty);
		
		String disabledAltroduct = "0";
		resultat.append(disabledAltroduct);
		
		String altUomCode = formatString("", 10);
		resultat.append(altUomCode);

		String fromFactor = formatNumber(null, 5);
		resultat.append(fromFactor);

		String toFactor = formatNumber(null, 5);
		resultat.append(toFactor);
		
		String sizeCode = formatString("", 50);
		resultat.append(sizeCode);
		
		String colorCode = formatString("", 50);
		resultat.append(colorCode);
		
		String source = formatString("", 50);
		resultat.append(source);
		
		String versionCode = formatString("", 50);
		resultat.append(versionCode);
		
		String reserveMark = formatString("", 1);
		resultat.append(reserveMark);

		String attribute = "[][][][][][][][][][][][][][][][][][][][]";
		resultat.append(attribute);

		resultat.append("\n");

		return resultat.toString();
	}

	private String formatString(String input, int size) {
		if (null == input) {
			input = "";
		}
		while (input.length() < size) {
			input += " ";
		}
		if (input.length() > size) {
			input = input.substring(0, size);
		}
		return input;
	}

	private String formatDouble(Double input) {

		if (null != input) {
	        String tmpFormat = decimalFormat.format(input.doubleValue());
	        tmpFormat = tmpFormat.replaceAll(",", "");
	
	        return tmpFormat;
		}
		return formatString("", 12);
	}

	private String formatNumber(Double input, int size) {
		String pattern = "";
		for (int i = 0; i < size; i++) {
			pattern += "0";
		}
		DecimalFormat numberFormat = new DecimalFormat(pattern);
		if (null != input) {
	        String tmpFormat = numberFormat.format(input.doubleValue());
	        return tmpFormat;
		}
		return formatString("", size);
	}

	private String formatInt(int input, int size) {
		String pattern = "";
		for (int i = 0; i < size; i++) {
			pattern += "0";
		}
		DecimalFormat numberFormat = new DecimalFormat(pattern);
        String tmpFormat = numberFormat.format(input);
        return tmpFormat;
	}

	public String formatDate(Date input) {
		if (null != input) {
			return dateFormat.format(input);
		}
		return "              ";
	}
}
